Abstract

This report explores the relationships between various factors influencing student performance, using exploratory data analysis (EDA) to identify key trends and correlations. The analysis focuses on variables such as study habits, access to resources, parental involvement, and environmental factors, and how they impact final exam scores. Insights gained from the data will inform recommendations aimed at improving academic outcomes for students.

Data Source

The dataset was sourced from Kaggle under the CC0 1.0 universal “No Copyright” license. We are free to copy, modify, distribute and perform the work, even for commercial purposes, all without asking permission. Learn more about this license here here.

URL for data in Kaggle: Student Performance Factors Dataset

Import and View Data

student_data <- read.csv('../data/StudentPerformanceFactors.csv', header = TRUE)
student_data    # Display the dataset

Summary Statistics

summary(student_data)   # Summary statistics for all variables
 Hours_Studied     Attendance     Parental_Involvement Access_to_Resources
 Min.   : 1.00   Min.   : 60.00   Length:6607          Length:6607        
 1st Qu.:16.00   1st Qu.: 70.00   Class :character     Class :character   
 Median :20.00   Median : 80.00   Mode  :character     Mode  :character   
 Mean   :19.98   Mean   : 79.98                                           
 3rd Qu.:24.00   3rd Qu.: 90.00                                           
 Max.   :44.00   Max.   :100.00                                           
 Extracurricular_Activities  Sleep_Hours     Previous_Scores 
 Length:6607                Min.   : 4.000   Min.   : 50.00  
 Class :character           1st Qu.: 6.000   1st Qu.: 63.00  
 Mode  :character           Median : 7.000   Median : 75.00  
                            Mean   : 7.029   Mean   : 75.07  
                            3rd Qu.: 8.000   3rd Qu.: 88.00  
                            Max.   :10.000   Max.   :100.00  
 Motivation_Level   Internet_Access    Tutoring_Sessions Family_Income     
 Length:6607        Length:6607        Min.   :0.000     Length:6607       
 Class :character   Class :character   1st Qu.:1.000     Class :character  
 Mode  :character   Mode  :character   Median :1.000     Mode  :character  
                                       Mean   :1.494                       
                                       3rd Qu.:2.000                       
                                       Max.   :8.000                       
 Teacher_Quality    School_Type        Peer_Influence     Physical_Activity
 Length:6607        Length:6607        Length:6607        Min.   :0.000    
 Class :character   Class :character   Class :character   1st Qu.:2.000    
 Mode  :character   Mode  :character   Mode  :character   Median :3.000    
                                                          Mean   :2.968    
                                                          3rd Qu.:4.000    
                                                          Max.   :6.000    
 Learning_Disabilities Parental_Education_Level Distance_from_Home
 Length:6607           Length:6607              Length:6607       
 Class :character      Class :character         Class :character  
 Mode  :character      Mode  :character         Mode  :character  
                                                                  
                                                                  
                                                                  
    Gender            Exam_Score    
 Length:6607        Min.   : 55.00  
 Class :character   1st Qu.: 65.00  
 Mode  :character   Median : 67.00  
                    Mean   : 67.24  
                    3rd Qu.: 69.00  
                    Max.   :101.00  
head(student_data)      # Display the first few rows of the dataset
str(student_data)       # Structure of the dataset
'data.frame':   6607 obs. of  20 variables:
 $ Hours_Studied             : int  23 19 24 29 19 19 29 25 17 23 ...
 $ Attendance                : int  84 64 98 89 92 88 84 78 94 98 ...
 $ Parental_Involvement      : chr  "Low" "Low" "Medium" "Low" ...
 $ Access_to_Resources       : chr  "High" "Medium" "Medium" "Medium" ...
 $ Extracurricular_Activities: chr  "No" "No" "Yes" "Yes" ...
 $ Sleep_Hours               : int  7 8 7 8 6 8 7 6 6 8 ...
 $ Previous_Scores           : int  73 59 91 98 65 89 68 50 80 71 ...
 $ Motivation_Level          : chr  "Low" "Low" "Medium" "Medium" ...
 $ Internet_Access           : chr  "Yes" "Yes" "Yes" "Yes" ...
 $ Tutoring_Sessions         : int  0 2 2 1 3 3 1 1 0 0 ...
 $ Family_Income             : chr  "Low" "Medium" "Medium" "Medium" ...
 $ Teacher_Quality           : chr  "Medium" "Medium" "Medium" "Medium" ...
 $ School_Type               : chr  "Public" "Public" "Public" "Public" ...
 $ Peer_Influence            : chr  "Positive" "Negative" "Neutral" "Negative" ...
 $ Physical_Activity         : int  3 4 4 4 4 3 2 2 1 5 ...
 $ Learning_Disabilities     : chr  "No" "No" "No" "No" ...
 $ Parental_Education_Level  : chr  "High School" "College" "Postgraduate" "High School" ...
 $ Distance_from_Home        : chr  "Near" "Moderate" "Near" "Moderate" ...
 $ Gender                    : chr  "Male" "Female" "Male" "Male" ...
 $ Exam_Score                : int  67 61 74 71 70 71 67 66 69 72 ...
sum(is.na(student_data))    # Check for missing values
[1] 0

Distribution of Final Exam Scores

Distribution of Final Exam Scores(Without Considering Other Factors)

Here we will explore the distribution of final exam scores among students with without considering other factors. To find our the distribution of final exam scores, we first need to sample the data and plot a histogram.

# Sample the data
set.seed(123)
exam_score_sample <- student_data$Exam_Score[sample(nrow(student_data), 100)]
exam_score_sample
  [1] 68 66 74 63 71 67 62 74 67 63 64 72 59 63 63 69 68 63 71 70 66 61 68 71 64
 [26] 64 69 73 70 65 72 65 64 70 69 69 62 68 68 71 69 73 73 66 65 65 69 67 68 69
 [51] 67 65 66 61 66 68 70 66 67 68 70 72 75 67 65 69 72 68 66 66 67 64 65 72 67
 [76] 71 69 59 69 69 66 68 63 67 62 63 72 65 65 63 58 67 65 69 71 66 67 65 61 71
# Plot histogram
hist(exam_score_sample, main = "Distribution of Final Exam Scores", xlab = "Final Exam Score", col = "skyblue", border = "black")

From the histogram, we can see that the distribution of final exam scores is approximately normal. We now plot a boxplot to visualize the spread of scores and identify any outliers.

# Boxplot of final exam scores
boxplot(exam_score_sample, main = "Boxplot of Final Exam Scores", col = "skyblue", border = "black")

The boxplot shows that the distribution of final exam scores is centered around the median, with a few outliers on the lower end of the scale. Now we use numerical methods to confirm the normality of the distribution.

# Shapiro-Wilk test for normality
shapiro.test(exam_score_sample)

    Shapiro-Wilk normality test

data:  exam_score_sample
W = 0.98776, p-value = 0.4903

The Shapiro-Wilk test confirms that the distribution of final exam scores is approximately normal, with a p-value greater than 0.05.

Distribution of Final Exam Scores (Parental_Involvement Category)

Next, we explore the distribution of final exam scores based on parental involvement levels. We will create a boxplot to compare the scores of students with different levels of parental involvement.

# Sample the data
high_parental_involvement <- student_data$Exam_Score[student_data$Parental_Involvement == "High"][sample(sum(student_data$Parental_Involvement == "High"), 100)]
medium_parental_involvement <- student_data$Exam_Score[student_data$Parental_Involvement == "Medium"][sample(sum(student_data$Parental_Involvement == "Medium"), 100)]
low_parental_involvement <- student_data$Exam_Score[student_data$Parental_Involvement == "Low"][sample(sum(student_data$Parental_Involvement == "Low"), 100)]

# Histogram of final exam scores by parental involvement
par(mfrow = c(1, 3))
hist(high_parental_involvement, main = "High Parental Involvement", xlab = "Final Exam Score", col = "skyblue", border = "black")
hist(medium_parental_involvement, main = "Medium Parental Involvement", xlab = "Final Exam Score", col = "skyblue", border = "black")
hist(low_parental_involvement, main = "Low Parental Involvement", xlab = "Final Exam Score", col = "skyblue", border = "black")

The three histograms show the distribution of final exam scores for students with high, medium, and low levels of parental involvement. We can see that the distribution of the scores seems to be similar across all three categories. They seem to follow a normal distribution, with a slight skew towards higher scores for students with high parental involvement. We now use numerical methods to confirm the normality of the distributions.

# Shapiro-Wilk test for normality
shapiro.test(high_parental_involvement)

    Shapiro-Wilk normality test

data:  high_parental_involvement
W = 0.9794, p-value = 0.1194
shapiro.test(medium_parental_involvement)

    Shapiro-Wilk normality test

data:  medium_parental_involvement
W = 0.98125, p-value = 0.1662
shapiro.test(low_parental_involvement)

    Shapiro-Wilk normality test

data:  low_parental_involvement
W = 0.96994, p-value = 0.02186

The Shapiro-Wilk test confirms that the distributions of final exam scores for students with high and medium levels of parental involvement are approximately normal, with p-values greater than 0.05. However, the distribution for students with low parental involvement is slightly skewed, with a p-value less than 0.05.

We now investigate the distribution of final exam scores for students with low parental involvement further. We will now plot a density plot to visualize the distribution more clearly.

# Density plot of final exam scores for students with low parental involvement
plot(density(low_parental_involvement), main = "Density Plot of Final Exam Scores for Low Parental Involvement", xlab = "Final Exam Score", col = "skyblue")

The density plot shows that the distribution of final exam is slightly skewed to the left for students with low parental involvement. We will now create a QQ plot to compare the distribution of scores to a normal distribution.

# QQ plot of final exam scores for students with low parental involvement
qqnorm(low_parental_involvement, main = "QQ Plot of Final Exam Scores for Low Parental Involvement", col = "skyblue")
qqline(low_parental_involvement, col = "red")

The QQ plot confirms that the distribution of final exam scores for students with low parental involvement is slightly skewed to the left, deviating from a normal distribution.

Distribution of Final Exam Scores (Access_to_Resources Category)

Next, we explore the distribution of final exam scores based on access to resources. We will create a boxplot to compare the scores of students with different levels of access to resources.

# Sample the data
high_access_to_resources <- student_data$Exam_Score[student_data$Access_to_Resources == "High"][sample(sum(student_data$Access_to_Resources == "High"), 100)]
medium_access_to_resources <- student_data$Exam_Score[student_data$Access_to_Resources == "Medium"][sample(sum(student_data$Access_to_Resources == "Medium"), 100)]
low_access_to_resources <- student_data$Exam_Score[student_data$Access_to_Resources == "Low"][sample(sum(student_data$Access_to_Resources == "Low"), 100)]

# Histogram of final exam scores by access to resources
par(mfrow = c(1, 3))
hist(high_access_to_resources, main = "High Access to Resources", xlab = "Final Exam Score", col = "skyblue", border = "black")
hist(medium_access_to_resources, main = "Medium Access to Resources", xlab = "Final Exam Score", col = "skyblue", border = "black")
hist(low_access_to_resources, main = "Low Access to Resources", xlab = "Final Exam Score", col = "skyblue", border = "black")

plot(density(low_access_to_resources), main = "Low Access to Resources", xlab = "Final Exam Score", col = "skyblue")
plot(density(medium_access_to_resources), main = "Medium Access to Resources", xlab = "Final Exam Score", col = "skyblue")
plot(density(high_access_to_resources), main = "High Access to Resources", xlab = "Final Exam Score", col = "skyblue")

The histograms and density plots show the distribution of final exam scores for students with high, medium, and low levels of access to resources. The distributions seem to be similar across all three categories, with a slight skew towards higher scores for students with high access to resources. We will now use numerical methods to confirm the normality of the distributions.

# Shapiro-Wilk test for normality
shapiro.test(high_access_to_resources)

    Shapiro-Wilk normality test

data:  high_access_to_resources
W = 0.85758, p-value = 2.283e-08
shapiro.test(medium_access_to_resources)

    Shapiro-Wilk normality test

data:  medium_access_to_resources
W = 0.73995, p-value = 5.121e-12
shapiro.test(low_access_to_resources)

    Shapiro-Wilk normality test

data:  low_access_to_resources
W = 0.77633, p-value = 4.942e-11

The Shapiro-Wilk test shows that the distribution of all three categories of access to resources is not normal, with p-values less than 0.05. This indicates that the distribution of final exam scores is skewed for students with different levels of access to resources.

Distribution of Final Exam Scores (Extracurricular_Activities Category)

Next, we explore the distribution of final exam scores based on participation in extracurricular activities. We will create a boxplot to compare the scores of students who participate in extracurricular activities and those who do not.

# Sample the data
participate_extracurricular <- student_data$Exam_Score[student_data$Extracurricular_Activities == "Yes"][sample(sum(student_data$Extracurricular_Activities == "Yes"), 100)]
do_not_participate_extracurricular <- student_data$Exam_Score[student_data$Extracurricular_Activities == "No"][sample(sum(student_data$Extracurricular_Activities == "No"), 100)]

# Boxplot of final exam scores by extracurricular activities
boxplot(student_data$Exam_Score ~ student_data$Extracurricular_Activities, main = "Final Exam Scores by Extracurricular Activities", xlab = "Extracurricular Activities", ylab = "Final Exam Score", col = "skyblue", border = "black")

The boxplot shows that students who participate in extracurricular activities tend to have higher final exam scores compared to those who do not. Now we will visualize the distribution of scores for both groups using histograms.

# Histogram of final exam scores by extracurricular activities
par(mfrow = c(1, 2))
hist(participate_extracurricular, main = "Extracurricular Activities", xlab = "Final Exam Score", col = "skyblue", border = "black")
hist(do_not_participate_extracurricular, main = "No Extracurricular Activities", xlab = "Final Exam Score", col = "skyblue", border = "black")

Both histograms show right skewed distributions, with students who participate in extracurricular activities having higher final exam scores. We will now use numerical methods to confirm the normality of the distributions with the following hypothesis test.

  • Null Hypothesis (\(H_0\)): The distribution of final exam scores for students who participate in extracurricular activities is normal.
  • Alternative Hypothesis (\(H_1\)): The distribution of final exam scores for students who participate in extracurricular activities is not normal.
# Shapiro-Wilk test for normality
shapiro.test(participate_extracurricular)

    Shapiro-Wilk normality test

data:  participate_extracurricular
W = 0.88155, p-value = 2.112e-07

The Shapiro-Wilk test confirms that the distribution of final exam scores for students who participate in extracurricular activities is not normal, with a p-value less than 0.05. Thus, we reject the null hypothesis.

Distribution of Final Exam Scores (Motivation_Level Category)

Next we explore the distribution of final exam scores based on motivation levels. We will create a histogram to compare the scores of students with different motivation levels.

# Smaple Data
high_motivation <- student_data$Exam_Score[student_data$Motivation_Level == "High"][sample(sum(student_data$Motivation_Level == "High"), 100)]
medium_motivation <- student_data$Exam_Score[student_data$Motivation_Level == "High"][sample(sum(student_data$Motivation_Level == "Medium"), 100)]
low_motivation <- student_data$Exam_Score[student_data$Motivation_Level == "High"][sample(sum(student_data$Motivation_Level == "Low"), 100)]

# Histogram of final exam scores by motivation level
par(mfrow = c(1, 3))
hist(high_motivation, main = "High Motivation Level", xlab = "Final Exam Score", col = "skyblue", border = "black")
hist(medium_motivation, main = "Medium Motivation Level", xlab = "Final Exam Score", col = "skyblue", border = "black")
hist(low_motivation, main = "Low Motivation Level", xlab = "Final Exam Score", col = "skyblue", border = "black")

The histograms for High and medium motivation levels show a normal distribution of final exam scores, while the low motivation level histogram shows a right-skewed distribution. We will now use numerical methods to confirm the normality of the distributions.

# Shapiro-Wilk test for normality
shapiro.test(high_motivation)

    Shapiro-Wilk normality test

data:  high_motivation
W = 0.98236, p-value = 0.202
shapiro.test(medium_motivation)

    Shapiro-Wilk normality test

data:  medium_motivation
W = 0.9695, p-value = 0.4479
shapiro.test(low_motivation)

    Shapiro-Wilk normality test

data:  low_motivation
W = 0.73846, p-value = 2.385e-09

The Shapiro-Wilk test confirms that the distributions of final exam scores for students with high and medium motivation levels are approximately normal, with p-values greater than 0.05. However, the distribution for students with low motivation levels is slightly skewed, with a p-value less than 0.05.

Summary of Distribution Analysis

In summary, the distribution of final exam scores is approximately normal when considering all students. However, when examining the scores based on other factors such as parental involvement, access to resources, extracurricular activities, and motivation levels, the distributions vary. Students with high parental involvement and high access to resources tend to have higher final exam scores, while students who participate in extracurricular activities also perform better. Motivation levels also play a role in student performance, with students who are highly motivated achieving higher scores.

Average number of hours students study per week

Average Number of Hours Students Study per Week (Without Considering Other Factors)

Next, we explore the average number of hours students study per week without considering other factors.

# Summary statistics for study hours
summary(student_data$Hours_Studied)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
   1.00   16.00   20.00   19.98   24.00   44.00 

The summary statistics show that the average number of hours students study per week is approximately 19.98 hours. We will now visualize the distribution of study hours using a histogram.

# Histogram of study hours
hist(student_data$Hours_Studied, main = "Distribution of Study Hours", xlab = "Study Hours", col = "skyblue", border = "black")

Average Number of Hours Students Study per Week (Parental_Involvement Category)

Next, we will explore the average number of hours students study per week based on parental involvement levels.

# Summary statistics for study hours by parental involvement
summary(student_data$Hours_Studied[student_data$Parental_Involvement == "High"])
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
   1.00   16.00   20.00   19.85   24.00   44.00 
summary(student_data$Hours_Studied[student_data$Parental_Involvement == "Medium"])
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
   1.00   16.00   20.00   19.98   24.00   39.00 
summary(student_data$Hours_Studied[student_data$Parental_Involvement == "Low"])
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
   2.00   16.00   20.00   20.13   24.00   38.00 

The summary statistics of the average number of hours students study per week based on parental involvement levels do not show significant differences. We will now use ANOVA to test for differences in study hours based on parental involvement levels. But first, we need to check the assumptions of ANOVA.

# Sample the data
high_parental_involvement <- student_data$Hours_Studied[student_data$Parental_Involvement == "High"][sample(sum(student_data$Parental_Involvement == "High"), 100)]
medium_parental_involvement <- student_data$Hours_Studied[student_data$Parental_Involvement == "Medium"][sample(sum(student_data$Parental_Involvement == "Medium"), 100)]
low_parental_involvement <- student_data$Hours_Studied[student_data$Parental_Involvement == "Low"][sample(sum(student_data$Parental_Involvement == "Low"), 100)]

# Histogram of study hours by parental involvement
par(mfrow = c(1, 3))
hist(high_parental_involvement, main = "High Parental Involvement", xlab = "Study Hours", col = "skyblue", border = "black")
hist(medium_parental_involvement, main = "Medium Parental Involvement", xlab = "Study Hours", col = "skyblue", border = "black")
hist(low_parental_involvement, main = "Low Parental Involvement", xlab = "Study Hours", col = "skyblue", border = "black")

# Check assumptions of ANOVA
shapiro.test(high_parental_involvement)

    Shapiro-Wilk normality test

data:  high_parental_involvement
W = 0.98554, p-value = 0.3473
shapiro.test(medium_parental_involvement)

    Shapiro-Wilk normality test

data:  medium_parental_involvement
W = 0.97749, p-value = 0.08461
shapiro.test(low_parental_involvement)

    Shapiro-Wilk normality test

data:  low_parental_involvement
W = 0.98649, p-value = 0.4041

Both the histograms and the Shapiro-Wilk test show that the distribution of study hours is approximately normal for all students. We will now use ANOVA to test for differences in study hours based on parental involvement levels.

# ANOVA test for study hours by parental involvement
anova_parental_involvement <- aov(Hours_Studied ~ Parental_Involvement, data = student_data)
summary(anova_parental_involvement)
                       Df Sum Sq Mean Sq F value Pr(>F)
Parental_Involvement    2     62   30.86    0.86  0.423
Residuals            6604 237009   35.89               
LS0tDQp0aXRsZTogIkdlbmVyYWwgVHJlbmRzIGFuZCBEZXNjcmlwdGl2ZSBBbmFseXNpcyINCmF1dGhvcjogIiZjb3B5OyBIZWN0b3IgTWF0aG9uc2kiDQpkYXRlOiAyMDI0LTEwLTE5DQpvdXRwdXQ6DQogICAgaHRtbF9ub3RlYm9vazoNCiAgICAgICAgdGhlbWU6IGZsYXRseQ0KICAgICAgICBoaWdobGlnaHQ6IHRhbmdvDQogICAgICAgIHRvYzogdHJ1ZQ0KICAgICAgICB0b2NfZmxvYXQ6IHRydWUNCi0tLQ0KDQotLS0tLQ0KDQojIEFic3RyYWN0DQoNClRoaXMgcmVwb3J0IGV4cGxvcmVzIHRoZSByZWxhdGlvbnNoaXBzIGJldHdlZW4gdmFyaW91cyBmYWN0b3JzIGluZmx1ZW5jaW5nIHN0dWRlbnQgcGVyZm9ybWFuY2UsIHVzaW5nIGV4cGxvcmF0b3J5IGRhdGEgYW5hbHlzaXMgKEVEQSkgdG8gaWRlbnRpZnkga2V5IHRyZW5kcyBhbmQgY29ycmVsYXRpb25zLiBUaGUgYW5hbHlzaXMgZm9jdXNlcyBvbiB2YXJpYWJsZXMgc3VjaCBhcyBzdHVkeSBoYWJpdHMsIGFjY2VzcyB0byByZXNvdXJjZXMsIHBhcmVudGFsIGludm9sdmVtZW50LCBhbmQgZW52aXJvbm1lbnRhbCBmYWN0b3JzLCBhbmQgaG93IHRoZXkgaW1wYWN0IGZpbmFsIGV4YW0gc2NvcmVzLiBJbnNpZ2h0cyBnYWluZWQgZnJvbSB0aGUgZGF0YSB3aWxsIGluZm9ybSByZWNvbW1lbmRhdGlvbnMgYWltZWQgYXQgaW1wcm92aW5nIGFjYWRlbWljIG91dGNvbWVzIGZvciBzdHVkZW50cy4NCg0KIyBEYXRhIFNvdXJjZQ0KDQpUaGUgZGF0YXNldCB3YXMgc291cmNlZCBmcm9tIEthZ2dsZSB1bmRlciB0aGUgQ0MwIDEuMCB1bml2ZXJzYWwgIk5vIENvcHlyaWdodCIgbGljZW5zZS4gV2UgYXJlIGZyZWUgdG8gY29weSwgbW9kaWZ5LCBkaXN0cmlidXRlIGFuZCBwZXJmb3JtIHRoZSB3b3JrLCBldmVuIGZvciBjb21tZXJjaWFsIHB1cnBvc2VzLCBhbGwgd2l0aG91dCBhc2tpbmcgcGVybWlzc2lvbi4gTGVhcm4gbW9yZSBhYm91dCB0aGlzIGxpY2Vuc2UgaGVyZSBbaGVyZV0oaHR0cHM6Ly9jcmVhdGl2ZWNvbW1vbnMub3JnL3B1YmxpY2RvbWFpbi96ZXJvLzEuMC8pLg0KDQpVUkwgZm9yIGRhdGEgaW4gS2FnZ2xlOiBbU3R1ZGVudCBQZXJmb3JtYW5jZSBGYWN0b3JzIERhdGFzZXRdKGh0dHBzOi8vd3d3LmthZ2dsZS5jb20vZGF0YXNldHMvbGFpbmd1eW4xMjMvc3R1ZGVudC1wZXJmb3JtYW5jZS1mYWN0b3JzKQ0KDQojIEltcG9ydCBhbmQgVmlldyBEYXRhDQoNCmBgYHtyfQ0Kc3R1ZGVudF9kYXRhIDwtIHJlYWQuY3N2KCcuLi9kYXRhL1N0dWRlbnRQZXJmb3JtYW5jZUZhY3RvcnMuY3N2JywgaGVhZGVyID0gVFJVRSkNCnN0dWRlbnRfZGF0YSAgICAjIERpc3BsYXkgdGhlIGRhdGFzZXQNCmBgYA0KDQojIyMgU3VtbWFyeSBTdGF0aXN0aWNzDQoNCmBgYHtyfQ0Kc3VtbWFyeShzdHVkZW50X2RhdGEpICAgIyBTdW1tYXJ5IHN0YXRpc3RpY3MgZm9yIGFsbCB2YXJpYWJsZXMNCmhlYWQoc3R1ZGVudF9kYXRhKSAgICAgICMgRGlzcGxheSB0aGUgZmlyc3QgZmV3IHJvd3Mgb2YgdGhlIGRhdGFzZXQNCnN0cihzdHVkZW50X2RhdGEpICAgICAgICMgU3RydWN0dXJlIG9mIHRoZSBkYXRhc2V0DQpzdW0oaXMubmEoc3R1ZGVudF9kYXRhKSkgICAgIyBDaGVjayBmb3IgbWlzc2luZyB2YWx1ZXMNCmBgYA0KDQojIERpc3RyaWJ1dGlvbiBvZiBGaW5hbCBFeGFtIFNjb3Jlcw0KDQojIyBEaXN0cmlidXRpb24gb2YgRmluYWwgRXhhbSBTY29yZXMoV2l0aG91dCBDb25zaWRlcmluZyBPdGhlciBGYWN0b3JzKQ0KSGVyZSB3ZSB3aWxsIGV4cGxvcmUgdGhlIGRpc3RyaWJ1dGlvbiBvZiBmaW5hbCBleGFtIHNjb3JlcyBhbW9uZyBzdHVkZW50cyB3aXRoIHdpdGhvdXQgY29uc2lkZXJpbmcgb3RoZXIgZmFjdG9ycy4NClRvIGZpbmQgb3VyIHRoZSBkaXN0cmlidXRpb24gb2YgZmluYWwgZXhhbSBzY29yZXMsIHdlIGZpcnN0IG5lZWQgdG8gc2FtcGxlIHRoZSBkYXRhIGFuZCBwbG90IGEgaGlzdG9ncmFtLg0KYGBge3J9DQojIFNhbXBsZSB0aGUgZGF0YQ0Kc2V0LnNlZWQoMTIzKQ0KZXhhbV9zY29yZV9zYW1wbGUgPC0gc3R1ZGVudF9kYXRhJEV4YW1fU2NvcmVbc2FtcGxlKG5yb3coc3R1ZGVudF9kYXRhKSwgMTAwKV0NCmV4YW1fc2NvcmVfc2FtcGxlDQoNCiMgUGxvdCBoaXN0b2dyYW0NCmhpc3QoZXhhbV9zY29yZV9zYW1wbGUsIG1haW4gPSAiRGlzdHJpYnV0aW9uIG9mIEZpbmFsIEV4YW0gU2NvcmVzIiwgeGxhYiA9ICJGaW5hbCBFeGFtIFNjb3JlIiwgY29sID0gInNreWJsdWUiLCBib3JkZXIgPSAiYmxhY2siKQ0KYGBgDQoNCkZyb20gdGhlIGhpc3RvZ3JhbSwgd2UgY2FuIHNlZSB0aGF0IHRoZSBkaXN0cmlidXRpb24gb2YgZmluYWwgZXhhbSBzY29yZXMgaXMgYXBwcm94aW1hdGVseSBub3JtYWwuIFdlIG5vdyBwbG90IGEgYm94cGxvdCB0byB2aXN1YWxpemUgdGhlIHNwcmVhZCBvZiBzY29yZXMgYW5kIGlkZW50aWZ5IGFueSBvdXRsaWVycy4NCmBgYHtyfQ0KIyBCb3hwbG90IG9mIGZpbmFsIGV4YW0gc2NvcmVzDQpib3hwbG90KGV4YW1fc2NvcmVfc2FtcGxlLCBtYWluID0gIkJveHBsb3Qgb2YgRmluYWwgRXhhbSBTY29yZXMiLCBjb2wgPSAic2t5Ymx1ZSIsIGJvcmRlciA9ICJibGFjayIpDQpgYGANCg0KVGhlIGJveHBsb3Qgc2hvd3MgdGhhdCB0aGUgZGlzdHJpYnV0aW9uIG9mIGZpbmFsIGV4YW0gc2NvcmVzIGlzIGNlbnRlcmVkIGFyb3VuZCB0aGUgbWVkaWFuLCB3aXRoIGEgZmV3IG91dGxpZXJzIG9uIHRoZSBsb3dlciBlbmQgb2YgdGhlIHNjYWxlLiBOb3cgd2UgdXNlIG51bWVyaWNhbCBtZXRob2RzIHRvIGNvbmZpcm0gdGhlIG5vcm1hbGl0eSBvZiB0aGUgZGlzdHJpYnV0aW9uLg0KYGBge3J9DQojIFNoYXBpcm8tV2lsayB0ZXN0IGZvciBub3JtYWxpdHkNCnNoYXBpcm8udGVzdChleGFtX3Njb3JlX3NhbXBsZSkNCmBgYA0KDQpUaGUgU2hhcGlyby1XaWxrIHRlc3QgY29uZmlybXMgdGhhdCB0aGUgZGlzdHJpYnV0aW9uIG9mIGZpbmFsIGV4YW0gc2NvcmVzIGlzIGFwcHJveGltYXRlbHkgbm9ybWFsLCB3aXRoIGEgcC12YWx1ZSBncmVhdGVyIHRoYW4gMC4wNS4NCg0KIyMgRGlzdHJpYnV0aW9uIG9mIEZpbmFsIEV4YW0gU2NvcmVzIChQYXJlbnRhbF9JbnZvbHZlbWVudCBDYXRlZ29yeSkNCg0KTmV4dCwgd2UgZXhwbG9yZSB0aGUgZGlzdHJpYnV0aW9uIG9mIGZpbmFsIGV4YW0gc2NvcmVzIGJhc2VkIG9uIHBhcmVudGFsIGludm9sdmVtZW50IGxldmVscy4gV2Ugd2lsbCBjcmVhdGUgYSBib3hwbG90IHRvIGNvbXBhcmUgdGhlIHNjb3JlcyBvZiBzdHVkZW50cyB3aXRoIGRpZmZlcmVudCBsZXZlbHMgb2YgcGFyZW50YWwgaW52b2x2ZW1lbnQuDQpgYGB7cn0NCiMgU2FtcGxlIHRoZSBkYXRhDQpoaWdoX3BhcmVudGFsX2ludm9sdmVtZW50IDwtIHN0dWRlbnRfZGF0YSRFeGFtX1Njb3JlW3N0dWRlbnRfZGF0YSRQYXJlbnRhbF9JbnZvbHZlbWVudCA9PSAiSGlnaCJdW3NhbXBsZShzdW0oc3R1ZGVudF9kYXRhJFBhcmVudGFsX0ludm9sdmVtZW50ID09ICJIaWdoIiksIDEwMCldDQptZWRpdW1fcGFyZW50YWxfaW52b2x2ZW1lbnQgPC0gc3R1ZGVudF9kYXRhJEV4YW1fU2NvcmVbc3R1ZGVudF9kYXRhJFBhcmVudGFsX0ludm9sdmVtZW50ID09ICJNZWRpdW0iXVtzYW1wbGUoc3VtKHN0dWRlbnRfZGF0YSRQYXJlbnRhbF9JbnZvbHZlbWVudCA9PSAiTWVkaXVtIiksIDEwMCldDQpsb3dfcGFyZW50YWxfaW52b2x2ZW1lbnQgPC0gc3R1ZGVudF9kYXRhJEV4YW1fU2NvcmVbc3R1ZGVudF9kYXRhJFBhcmVudGFsX0ludm9sdmVtZW50ID09ICJMb3ciXVtzYW1wbGUoc3VtKHN0dWRlbnRfZGF0YSRQYXJlbnRhbF9JbnZvbHZlbWVudCA9PSAiTG93IiksIDEwMCldDQoNCiMgSGlzdG9ncmFtIG9mIGZpbmFsIGV4YW0gc2NvcmVzIGJ5IHBhcmVudGFsIGludm9sdmVtZW50DQpwYXIobWZyb3cgPSBjKDEsIDMpKQ0KaGlzdChoaWdoX3BhcmVudGFsX2ludm9sdmVtZW50LCBtYWluID0gIkhpZ2ggUGFyZW50YWwgSW52b2x2ZW1lbnQiLCB4bGFiID0gIkZpbmFsIEV4YW0gU2NvcmUiLCBjb2wgPSAic2t5Ymx1ZSIsIGJvcmRlciA9ICJibGFjayIpDQpoaXN0KG1lZGl1bV9wYXJlbnRhbF9pbnZvbHZlbWVudCwgbWFpbiA9ICJNZWRpdW0gUGFyZW50YWwgSW52b2x2ZW1lbnQiLCB4bGFiID0gIkZpbmFsIEV4YW0gU2NvcmUiLCBjb2wgPSAic2t5Ymx1ZSIsIGJvcmRlciA9ICJibGFjayIpDQpoaXN0KGxvd19wYXJlbnRhbF9pbnZvbHZlbWVudCwgbWFpbiA9ICJMb3cgUGFyZW50YWwgSW52b2x2ZW1lbnQiLCB4bGFiID0gIkZpbmFsIEV4YW0gU2NvcmUiLCBjb2wgPSAic2t5Ymx1ZSIsIGJvcmRlciA9ICJibGFjayIpDQpgYGANCg0KVGhlIHRocmVlIGhpc3RvZ3JhbXMgc2hvdyB0aGUgZGlzdHJpYnV0aW9uIG9mIGZpbmFsIGV4YW0gc2NvcmVzIGZvciBzdHVkZW50cyB3aXRoIGhpZ2gsIG1lZGl1bSwgYW5kIGxvdyBsZXZlbHMgb2YgcGFyZW50YWwgaW52b2x2ZW1lbnQuIFdlIGNhbiBzZWUgdGhhdCB0aGUgZGlzdHJpYnV0aW9uIG9mIHRoZSBzY29yZXMgc2VlbXMgdG8gYmUgc2ltaWxhciBhY3Jvc3MgYWxsIHRocmVlIGNhdGVnb3JpZXMuIFRoZXkgc2VlbSB0byBmb2xsb3cgYSBub3JtYWwgZGlzdHJpYnV0aW9uLCB3aXRoIGEgc2xpZ2h0IHNrZXcgdG93YXJkcyBoaWdoZXIgc2NvcmVzIGZvciBzdHVkZW50cyB3aXRoIGhpZ2ggcGFyZW50YWwgaW52b2x2ZW1lbnQuDQpXZSBub3cgdXNlIG51bWVyaWNhbCBtZXRob2RzIHRvIGNvbmZpcm0gdGhlIG5vcm1hbGl0eSBvZiB0aGUgZGlzdHJpYnV0aW9ucy4NCmBgYHtyfQ0KIyBTaGFwaXJvLVdpbGsgdGVzdCBmb3Igbm9ybWFsaXR5DQpzaGFwaXJvLnRlc3QoaGlnaF9wYXJlbnRhbF9pbnZvbHZlbWVudCkNCnNoYXBpcm8udGVzdChtZWRpdW1fcGFyZW50YWxfaW52b2x2ZW1lbnQpDQpzaGFwaXJvLnRlc3QobG93X3BhcmVudGFsX2ludm9sdmVtZW50KQ0KYGBgDQoNClRoZSBTaGFwaXJvLVdpbGsgdGVzdCBjb25maXJtcyB0aGF0IHRoZSBkaXN0cmlidXRpb25zIG9mIGZpbmFsIGV4YW0gc2NvcmVzIGZvciBzdHVkZW50cyB3aXRoIGhpZ2ggYW5kIG1lZGl1bSBsZXZlbHMgb2YgcGFyZW50YWwgaW52b2x2ZW1lbnQgYXJlIGFwcHJveGltYXRlbHkgbm9ybWFsLCB3aXRoIHAtdmFsdWVzIGdyZWF0ZXIgdGhhbiAwLjA1LiBIb3dldmVyLCB0aGUgZGlzdHJpYnV0aW9uIGZvciBzdHVkZW50cyB3aXRoIGxvdyBwYXJlbnRhbCBpbnZvbHZlbWVudCBpcyBzbGlnaHRseSBza2V3ZWQsIHdpdGggYSBwLXZhbHVlIGxlc3MgdGhhbiAwLjA1Lg0KDQpXZSBub3cgaW52ZXN0aWdhdGUgdGhlIGRpc3RyaWJ1dGlvbiBvZiBmaW5hbCBleGFtIHNjb3JlcyBmb3Igc3R1ZGVudHMgd2l0aCBsb3cgcGFyZW50YWwgaW52b2x2ZW1lbnQgZnVydGhlci4gV2Ugd2lsbCBub3cgcGxvdCBhIGRlbnNpdHkgcGxvdCB0byB2aXN1YWxpemUgdGhlIGRpc3RyaWJ1dGlvbiBtb3JlIGNsZWFybHkuDQpgYGB7cn0NCiMgRGVuc2l0eSBwbG90IG9mIGZpbmFsIGV4YW0gc2NvcmVzIGZvciBzdHVkZW50cyB3aXRoIGxvdyBwYXJlbnRhbCBpbnZvbHZlbWVudA0KcGxvdChkZW5zaXR5KGxvd19wYXJlbnRhbF9pbnZvbHZlbWVudCksIG1haW4gPSAiRGVuc2l0eSBQbG90IG9mIEZpbmFsIEV4YW0gU2NvcmVzIGZvciBMb3cgUGFyZW50YWwgSW52b2x2ZW1lbnQiLCB4bGFiID0gIkZpbmFsIEV4YW0gU2NvcmUiLCBjb2wgPSAic2t5Ymx1ZSIpDQpgYGANCg0KVGhlIGRlbnNpdHkgcGxvdCBzaG93cyB0aGF0IHRoZSBkaXN0cmlidXRpb24gb2YgZmluYWwgZXhhbSBpcyBzbGlnaHRseSBza2V3ZWQgdG8gdGhlIGxlZnQgZm9yIHN0dWRlbnRzIHdpdGggbG93IHBhcmVudGFsIGludm9sdmVtZW50LiBXZSB3aWxsIG5vdyBjcmVhdGUgYSBRUSBwbG90IHRvIGNvbXBhcmUgdGhlIGRpc3RyaWJ1dGlvbiBvZiBzY29yZXMgdG8gYSBub3JtYWwgZGlzdHJpYnV0aW9uLg0KDQpgYGB7cn0NCiMgUVEgcGxvdCBvZiBmaW5hbCBleGFtIHNjb3JlcyBmb3Igc3R1ZGVudHMgd2l0aCBsb3cgcGFyZW50YWwgaW52b2x2ZW1lbnQNCnFxbm9ybShsb3dfcGFyZW50YWxfaW52b2x2ZW1lbnQsIG1haW4gPSAiUVEgUGxvdCBvZiBGaW5hbCBFeGFtIFNjb3JlcyBmb3IgTG93IFBhcmVudGFsIEludm9sdmVtZW50IiwgY29sID0gInNreWJsdWUiKQ0KcXFsaW5lKGxvd19wYXJlbnRhbF9pbnZvbHZlbWVudCwgY29sID0gInJlZCIpDQpgYGANCg0KVGhlIFFRIHBsb3QgY29uZmlybXMgdGhhdCB0aGUgZGlzdHJpYnV0aW9uIG9mIGZpbmFsIGV4YW0gc2NvcmVzIGZvciBzdHVkZW50cyB3aXRoIGxvdyBwYXJlbnRhbCBpbnZvbHZlbWVudCBpcyBzbGlnaHRseSBza2V3ZWQgdG8gdGhlIGxlZnQsIGRldmlhdGluZyBmcm9tIGEgbm9ybWFsIGRpc3RyaWJ1dGlvbi4NCg0KIyMgRGlzdHJpYnV0aW9uIG9mIEZpbmFsIEV4YW0gU2NvcmVzIChBY2Nlc3NfdG9fUmVzb3VyY2VzIENhdGVnb3J5KQ0KDQpOZXh0LCB3ZSBleHBsb3JlIHRoZSBkaXN0cmlidXRpb24gb2YgZmluYWwgZXhhbSBzY29yZXMgYmFzZWQgb24gYWNjZXNzIHRvIHJlc291cmNlcy4gV2Ugd2lsbCBjcmVhdGUgYSBib3hwbG90IHRvIGNvbXBhcmUgdGhlIHNjb3JlcyBvZiBzdHVkZW50cyB3aXRoIGRpZmZlcmVudCBsZXZlbHMgb2YgYWNjZXNzIHRvIHJlc291cmNlcy4NCmBgYHtyfQ0KIyBTYW1wbGUgdGhlIGRhdGENCmhpZ2hfYWNjZXNzX3RvX3Jlc291cmNlcyA8LSBzdHVkZW50X2RhdGEkRXhhbV9TY29yZVtzdHVkZW50X2RhdGEkQWNjZXNzX3RvX1Jlc291cmNlcyA9PSAiSGlnaCJdW3NhbXBsZShzdW0oc3R1ZGVudF9kYXRhJEFjY2Vzc190b19SZXNvdXJjZXMgPT0gIkhpZ2giKSwgMTAwKV0NCm1lZGl1bV9hY2Nlc3NfdG9fcmVzb3VyY2VzIDwtIHN0dWRlbnRfZGF0YSRFeGFtX1Njb3JlW3N0dWRlbnRfZGF0YSRBY2Nlc3NfdG9fUmVzb3VyY2VzID09ICJNZWRpdW0iXVtzYW1wbGUoc3VtKHN0dWRlbnRfZGF0YSRBY2Nlc3NfdG9fUmVzb3VyY2VzID09ICJNZWRpdW0iKSwgMTAwKV0NCmxvd19hY2Nlc3NfdG9fcmVzb3VyY2VzIDwtIHN0dWRlbnRfZGF0YSRFeGFtX1Njb3JlW3N0dWRlbnRfZGF0YSRBY2Nlc3NfdG9fUmVzb3VyY2VzID09ICJMb3ciXVtzYW1wbGUoc3VtKHN0dWRlbnRfZGF0YSRBY2Nlc3NfdG9fUmVzb3VyY2VzID09ICJMb3ciKSwgMTAwKV0NCg0KIyBIaXN0b2dyYW0gb2YgZmluYWwgZXhhbSBzY29yZXMgYnkgYWNjZXNzIHRvIHJlc291cmNlcw0KcGFyKG1mcm93ID0gYygxLCAzKSkNCmhpc3QoaGlnaF9hY2Nlc3NfdG9fcmVzb3VyY2VzLCBtYWluID0gIkhpZ2ggQWNjZXNzIHRvIFJlc291cmNlcyIsIHhsYWIgPSAiRmluYWwgRXhhbSBTY29yZSIsIGNvbCA9ICJza3libHVlIiwgYm9yZGVyID0gImJsYWNrIikNCmhpc3QobWVkaXVtX2FjY2Vzc190b19yZXNvdXJjZXMsIG1haW4gPSAiTWVkaXVtIEFjY2VzcyB0byBSZXNvdXJjZXMiLCB4bGFiID0gIkZpbmFsIEV4YW0gU2NvcmUiLCBjb2wgPSAic2t5Ymx1ZSIsIGJvcmRlciA9ICJibGFjayIpDQpoaXN0KGxvd19hY2Nlc3NfdG9fcmVzb3VyY2VzLCBtYWluID0gIkxvdyBBY2Nlc3MgdG8gUmVzb3VyY2VzIiwgeGxhYiA9ICJGaW5hbCBFeGFtIFNjb3JlIiwgY29sID0gInNreWJsdWUiLCBib3JkZXIgPSAiYmxhY2siKQ0KDQpwbG90KGRlbnNpdHkobG93X2FjY2Vzc190b19yZXNvdXJjZXMpLCBtYWluID0gIkxvdyBBY2Nlc3MgdG8gUmVzb3VyY2VzIiwgeGxhYiA9ICJGaW5hbCBFeGFtIFNjb3JlIiwgY29sID0gInNreWJsdWUiKQ0KcGxvdChkZW5zaXR5KG1lZGl1bV9hY2Nlc3NfdG9fcmVzb3VyY2VzKSwgbWFpbiA9ICJNZWRpdW0gQWNjZXNzIHRvIFJlc291cmNlcyIsIHhsYWIgPSAiRmluYWwgRXhhbSBTY29yZSIsIGNvbCA9ICJza3libHVlIikNCnBsb3QoZGVuc2l0eShoaWdoX2FjY2Vzc190b19yZXNvdXJjZXMpLCBtYWluID0gIkhpZ2ggQWNjZXNzIHRvIFJlc291cmNlcyIsIHhsYWIgPSAiRmluYWwgRXhhbSBTY29yZSIsIGNvbCA9ICJza3libHVlIikNCmBgYA0KDQpUaGUgaGlzdG9ncmFtcyBhbmQgZGVuc2l0eSBwbG90cyBzaG93IHRoZSBkaXN0cmlidXRpb24gb2YgZmluYWwgZXhhbSBzY29yZXMgZm9yIHN0dWRlbnRzIHdpdGggaGlnaCwgbWVkaXVtLCBhbmQgbG93IGxldmVscyBvZiBhY2Nlc3MgdG8gcmVzb3VyY2VzLiBUaGUgZGlzdHJpYnV0aW9ucyBzZWVtIHRvIGJlIHNpbWlsYXIgYWNyb3NzIGFsbCB0aHJlZSBjYXRlZ29yaWVzLCB3aXRoIGEgc2xpZ2h0IHNrZXcgdG93YXJkcyBoaWdoZXIgc2NvcmVzIGZvciBzdHVkZW50cyB3aXRoIGhpZ2ggYWNjZXNzIHRvIHJlc291cmNlcy4gV2Ugd2lsbCBub3cgdXNlIG51bWVyaWNhbCBtZXRob2RzIHRvIGNvbmZpcm0gdGhlIG5vcm1hbGl0eSBvZiB0aGUgZGlzdHJpYnV0aW9ucy4NCg0KYGBge3J9DQojIFNoYXBpcm8tV2lsayB0ZXN0IGZvciBub3JtYWxpdHkNCnNoYXBpcm8udGVzdChoaWdoX2FjY2Vzc190b19yZXNvdXJjZXMpDQpzaGFwaXJvLnRlc3QobWVkaXVtX2FjY2Vzc190b19yZXNvdXJjZXMpDQpzaGFwaXJvLnRlc3QobG93X2FjY2Vzc190b19yZXNvdXJjZXMpDQpgYGANCg0KVGhlIFNoYXBpcm8tV2lsayB0ZXN0IHNob3dzIHRoYXQgdGhlIGRpc3RyaWJ1dGlvbiBvZiBhbGwgdGhyZWUgY2F0ZWdvcmllcyBvZiBhY2Nlc3MgdG8gcmVzb3VyY2VzIGlzIG5vdCBub3JtYWwsIHdpdGggcC12YWx1ZXMgbGVzcyB0aGFuIDAuMDUuIFRoaXMgaW5kaWNhdGVzIHRoYXQgdGhlIGRpc3RyaWJ1dGlvbiBvZiBmaW5hbCBleGFtIHNjb3JlcyBpcyBza2V3ZWQgZm9yIHN0dWRlbnRzIHdpdGggZGlmZmVyZW50IGxldmVscyBvZiBhY2Nlc3MgdG8gcmVzb3VyY2VzLg0KDQojIyBEaXN0cmlidXRpb24gb2YgRmluYWwgRXhhbSBTY29yZXMgKEV4dHJhY3VycmljdWxhcl9BY3Rpdml0aWVzIENhdGVnb3J5KQ0KDQpOZXh0LCB3ZSBleHBsb3JlIHRoZSBkaXN0cmlidXRpb24gb2YgZmluYWwgZXhhbSBzY29yZXMgYmFzZWQgb24gcGFydGljaXBhdGlvbiBpbiBleHRyYWN1cnJpY3VsYXIgYWN0aXZpdGllcy4gV2Ugd2lsbCBjcmVhdGUgYSBib3hwbG90IHRvIGNvbXBhcmUgdGhlIHNjb3JlcyBvZiBzdHVkZW50cyB3aG8gcGFydGljaXBhdGUgaW4gZXh0cmFjdXJyaWN1bGFyIGFjdGl2aXRpZXMgYW5kIHRob3NlIHdobyBkbyBub3QuDQpgYGB7cn0NCiMgU2FtcGxlIHRoZSBkYXRhDQpwYXJ0aWNpcGF0ZV9leHRyYWN1cnJpY3VsYXIgPC0gc3R1ZGVudF9kYXRhJEV4YW1fU2NvcmVbc3R1ZGVudF9kYXRhJEV4dHJhY3VycmljdWxhcl9BY3Rpdml0aWVzID09ICJZZXMiXVtzYW1wbGUoc3VtKHN0dWRlbnRfZGF0YSRFeHRyYWN1cnJpY3VsYXJfQWN0aXZpdGllcyA9PSAiWWVzIiksIDEwMCldDQpkb19ub3RfcGFydGljaXBhdGVfZXh0cmFjdXJyaWN1bGFyIDwtIHN0dWRlbnRfZGF0YSRFeGFtX1Njb3JlW3N0dWRlbnRfZGF0YSRFeHRyYWN1cnJpY3VsYXJfQWN0aXZpdGllcyA9PSAiTm8iXVtzYW1wbGUoc3VtKHN0dWRlbnRfZGF0YSRFeHRyYWN1cnJpY3VsYXJfQWN0aXZpdGllcyA9PSAiTm8iKSwgMTAwKV0NCg0KIyBCb3hwbG90IG9mIGZpbmFsIGV4YW0gc2NvcmVzIGJ5IGV4dHJhY3VycmljdWxhciBhY3Rpdml0aWVzDQpib3hwbG90KHN0dWRlbnRfZGF0YSRFeGFtX1Njb3JlIH4gc3R1ZGVudF9kYXRhJEV4dHJhY3VycmljdWxhcl9BY3Rpdml0aWVzLCBtYWluID0gIkZpbmFsIEV4YW0gU2NvcmVzIGJ5IEV4dHJhY3VycmljdWxhciBBY3Rpdml0aWVzIiwgeGxhYiA9ICJFeHRyYWN1cnJpY3VsYXIgQWN0aXZpdGllcyIsIHlsYWIgPSAiRmluYWwgRXhhbSBTY29yZSIsIGNvbCA9ICJza3libHVlIiwgYm9yZGVyID0gImJsYWNrIikNCmBgYA0KDQpUaGUgYm94cGxvdCBzaG93cyB0aGF0IHN0dWRlbnRzIHdobyBwYXJ0aWNpcGF0ZSBpbiBleHRyYWN1cnJpY3VsYXIgYWN0aXZpdGllcyB0ZW5kIHRvIGhhdmUgaGlnaGVyIGZpbmFsIGV4YW0gc2NvcmVzIGNvbXBhcmVkIHRvIHRob3NlIHdobyBkbyBub3QuIE5vdyB3ZSB3aWxsIHZpc3VhbGl6ZSB0aGUgZGlzdHJpYnV0aW9uIG9mIHNjb3JlcyBmb3IgYm90aCBncm91cHMgdXNpbmcgaGlzdG9ncmFtcy4NCmBgYHtyfQ0KIyBIaXN0b2dyYW0gb2YgZmluYWwgZXhhbSBzY29yZXMgYnkgZXh0cmFjdXJyaWN1bGFyIGFjdGl2aXRpZXMNCnBhcihtZnJvdyA9IGMoMSwgMikpDQpoaXN0KHBhcnRpY2lwYXRlX2V4dHJhY3VycmljdWxhciwgbWFpbiA9ICJFeHRyYWN1cnJpY3VsYXIgQWN0aXZpdGllcyIsIHhsYWIgPSAiRmluYWwgRXhhbSBTY29yZSIsIGNvbCA9ICJza3libHVlIiwgYm9yZGVyID0gImJsYWNrIikNCmhpc3QoZG9fbm90X3BhcnRpY2lwYXRlX2V4dHJhY3VycmljdWxhciwgbWFpbiA9ICJObyBFeHRyYWN1cnJpY3VsYXIgQWN0aXZpdGllcyIsIHhsYWIgPSAiRmluYWwgRXhhbSBTY29yZSIsIGNvbCA9ICJza3libHVlIiwgYm9yZGVyID0gImJsYWNrIikNCmBgYA0KDQpCb3RoIGhpc3RvZ3JhbXMgc2hvdyByaWdodCBza2V3ZWQgZGlzdHJpYnV0aW9ucywgd2l0aCBzdHVkZW50cyB3aG8gcGFydGljaXBhdGUgaW4gZXh0cmFjdXJyaWN1bGFyIGFjdGl2aXRpZXMgaGF2aW5nIGhpZ2hlciBmaW5hbCBleGFtIHNjb3Jlcy4gV2Ugd2lsbCBub3cgdXNlIG51bWVyaWNhbCBtZXRob2RzIHRvIGNvbmZpcm0gdGhlIG5vcm1hbGl0eSBvZiB0aGUgZGlzdHJpYnV0aW9ucyB3aXRoIHRoZSBmb2xsb3dpbmcgaHlwb3RoZXNpcyB0ZXN0Lg0KDQotIE51bGwgSHlwb3RoZXNpcyAoJEhfMCQpOiBUaGUgZGlzdHJpYnV0aW9uIG9mIGZpbmFsIGV4YW0gc2NvcmVzIGZvciBzdHVkZW50cyB3aG8gcGFydGljaXBhdGUgaW4gZXh0cmFjdXJyaWN1bGFyIGFjdGl2aXRpZXMgaXMgbm9ybWFsLg0KLSBBbHRlcm5hdGl2ZSBIeXBvdGhlc2lzICgkSF8xJCk6IFRoZSBkaXN0cmlidXRpb24gb2YgZmluYWwgZXhhbSBzY29yZXMgZm9yIHN0dWRlbnRzIHdobyBwYXJ0aWNpcGF0ZSBpbiBleHRyYWN1cnJpY3VsYXIgYWN0aXZpdGllcyBpcyBub3Qgbm9ybWFsLg0KDQpgYGB7cn0NCiMgU2hhcGlyby1XaWxrIHRlc3QgZm9yIG5vcm1hbGl0eQ0Kc2hhcGlyby50ZXN0KHBhcnRpY2lwYXRlX2V4dHJhY3VycmljdWxhcikNCmBgYA0KDQpUaGUgU2hhcGlyby1XaWxrIHRlc3QgY29uZmlybXMgdGhhdCB0aGUgZGlzdHJpYnV0aW9uIG9mIGZpbmFsIGV4YW0gc2NvcmVzIGZvciBzdHVkZW50cyB3aG8gcGFydGljaXBhdGUgaW4gZXh0cmFjdXJyaWN1bGFyIGFjdGl2aXRpZXMgaXMgbm90IG5vcm1hbCwgd2l0aCBhIHAtdmFsdWUgbGVzcyB0aGFuIDAuMDUuIFRodXMsIHdlIHJlamVjdCB0aGUgbnVsbCBoeXBvdGhlc2lzLg0KDQojIyBEaXN0cmlidXRpb24gb2YgRmluYWwgRXhhbSBTY29yZXMgKE1vdGl2YXRpb25fTGV2ZWwgQ2F0ZWdvcnkpDQoNCk5leHQgd2UgZXhwbG9yZSB0aGUgZGlzdHJpYnV0aW9uIG9mIGZpbmFsIGV4YW0gc2NvcmVzIGJhc2VkIG9uIG1vdGl2YXRpb24gbGV2ZWxzLiBXZSB3aWxsIGNyZWF0ZSBhIGhpc3RvZ3JhbSB0byBjb21wYXJlIHRoZSBzY29yZXMgb2Ygc3R1ZGVudHMgd2l0aCBkaWZmZXJlbnQgbW90aXZhdGlvbiBsZXZlbHMuDQpgYGB7cn0NCiMgU21hcGxlIERhdGENCmhpZ2hfbW90aXZhdGlvbiA8LSBzdHVkZW50X2RhdGEkRXhhbV9TY29yZVtzdHVkZW50X2RhdGEkTW90aXZhdGlvbl9MZXZlbCA9PSAiSGlnaCJdW3NhbXBsZShzdW0oc3R1ZGVudF9kYXRhJE1vdGl2YXRpb25fTGV2ZWwgPT0gIkhpZ2giKSwgMTAwKV0NCm1lZGl1bV9tb3RpdmF0aW9uIDwtIHN0dWRlbnRfZGF0YSRFeGFtX1Njb3JlW3N0dWRlbnRfZGF0YSRNb3RpdmF0aW9uX0xldmVsID09ICJIaWdoIl1bc2FtcGxlKHN1bShzdHVkZW50X2RhdGEkTW90aXZhdGlvbl9MZXZlbCA9PSAiTWVkaXVtIiksIDEwMCldDQpsb3dfbW90aXZhdGlvbiA8LSBzdHVkZW50X2RhdGEkRXhhbV9TY29yZVtzdHVkZW50X2RhdGEkTW90aXZhdGlvbl9MZXZlbCA9PSAiSGlnaCJdW3NhbXBsZShzdW0oc3R1ZGVudF9kYXRhJE1vdGl2YXRpb25fTGV2ZWwgPT0gIkxvdyIpLCAxMDApXQ0KDQojIEhpc3RvZ3JhbSBvZiBmaW5hbCBleGFtIHNjb3JlcyBieSBtb3RpdmF0aW9uIGxldmVsDQpwYXIobWZyb3cgPSBjKDEsIDMpKQ0KaGlzdChoaWdoX21vdGl2YXRpb24sIG1haW4gPSAiSGlnaCBNb3RpdmF0aW9uIExldmVsIiwgeGxhYiA9ICJGaW5hbCBFeGFtIFNjb3JlIiwgY29sID0gInNreWJsdWUiLCBib3JkZXIgPSAiYmxhY2siKQ0KaGlzdChtZWRpdW1fbW90aXZhdGlvbiwgbWFpbiA9ICJNZWRpdW0gTW90aXZhdGlvbiBMZXZlbCIsIHhsYWIgPSAiRmluYWwgRXhhbSBTY29yZSIsIGNvbCA9ICJza3libHVlIiwgYm9yZGVyID0gImJsYWNrIikNCmhpc3QobG93X21vdGl2YXRpb24sIG1haW4gPSAiTG93IE1vdGl2YXRpb24gTGV2ZWwiLCB4bGFiID0gIkZpbmFsIEV4YW0gU2NvcmUiLCBjb2wgPSAic2t5Ymx1ZSIsIGJvcmRlciA9ICJibGFjayIpDQpgYGANCg0KVGhlIGhpc3RvZ3JhbXMgZm9yIEhpZ2ggYW5kIG1lZGl1bSBtb3RpdmF0aW9uIGxldmVscyBzaG93IGEgbm9ybWFsIGRpc3RyaWJ1dGlvbiBvZiBmaW5hbCBleGFtIHNjb3Jlcywgd2hpbGUgdGhlIGxvdyBtb3RpdmF0aW9uIGxldmVsIGhpc3RvZ3JhbSBzaG93cyBhIHJpZ2h0LXNrZXdlZCBkaXN0cmlidXRpb24uIFdlIHdpbGwgbm93IHVzZSBudW1lcmljYWwgbWV0aG9kcyB0byBjb25maXJtIHRoZSBub3JtYWxpdHkgb2YgdGhlIGRpc3RyaWJ1dGlvbnMuDQoNCmBgYHtyfQ0KIyBTaGFwaXJvLVdpbGsgdGVzdCBmb3Igbm9ybWFsaXR5DQpzaGFwaXJvLnRlc3QoaGlnaF9tb3RpdmF0aW9uKQ0Kc2hhcGlyby50ZXN0KG1lZGl1bV9tb3RpdmF0aW9uKQ0Kc2hhcGlyby50ZXN0KGxvd19tb3RpdmF0aW9uKQ0KYGBgDQoNClRoZSBTaGFwaXJvLVdpbGsgdGVzdCBjb25maXJtcyB0aGF0IHRoZSBkaXN0cmlidXRpb25zIG9mIGZpbmFsIGV4YW0gc2NvcmVzIGZvciBzdHVkZW50cyB3aXRoIGhpZ2ggYW5kIG1lZGl1bSBtb3RpdmF0aW9uIGxldmVscyBhcmUgYXBwcm94aW1hdGVseSBub3JtYWwsIHdpdGggcC12YWx1ZXMgZ3JlYXRlciB0aGFuIDAuMDUuIEhvd2V2ZXIsIHRoZSBkaXN0cmlidXRpb24gZm9yIHN0dWRlbnRzIHdpdGggbG93IG1vdGl2YXRpb24gbGV2ZWxzIGlzIHNsaWdodGx5IHNrZXdlZCwgd2l0aCBhIHAtdmFsdWUgbGVzcyB0aGFuIDAuMDUuDQoNCiMjIFN1bW1hcnkgb2YgRGlzdHJpYnV0aW9uIEFuYWx5c2lzDQoNCkluIHN1bW1hcnksIHRoZSBkaXN0cmlidXRpb24gb2YgZmluYWwgZXhhbSBzY29yZXMgaXMgYXBwcm94aW1hdGVseSBub3JtYWwgd2hlbiBjb25zaWRlcmluZyBhbGwgc3R1ZGVudHMuIEhvd2V2ZXIsIHdoZW4gZXhhbWluaW5nIHRoZSBzY29yZXMgYmFzZWQgb24gb3RoZXIgZmFjdG9ycyBzdWNoIGFzIHBhcmVudGFsIGludm9sdmVtZW50LCBhY2Nlc3MgdG8gcmVzb3VyY2VzLCBleHRyYWN1cnJpY3VsYXIgYWN0aXZpdGllcywgYW5kIG1vdGl2YXRpb24gbGV2ZWxzLCB0aGUgZGlzdHJpYnV0aW9ucyB2YXJ5LiBTdHVkZW50cyB3aXRoIGhpZ2ggcGFyZW50YWwgaW52b2x2ZW1lbnQgYW5kIGhpZ2ggYWNjZXNzIHRvIHJlc291cmNlcyB0ZW5kIHRvIGhhdmUgaGlnaGVyIGZpbmFsIGV4YW0gc2NvcmVzLCB3aGlsZSBzdHVkZW50cyB3aG8gcGFydGljaXBhdGUgaW4gZXh0cmFjdXJyaWN1bGFyIGFjdGl2aXRpZXMgYWxzbyBwZXJmb3JtIGJldHRlci4gTW90aXZhdGlvbiBsZXZlbHMgYWxzbyBwbGF5IGEgcm9sZSBpbiBzdHVkZW50IHBlcmZvcm1hbmNlLCB3aXRoIHN0dWRlbnRzIHdobyBhcmUgaGlnaGx5IG1vdGl2YXRlZCBhY2hpZXZpbmcgaGlnaGVyIHNjb3Jlcy4NCg0KIyBBdmVyYWdlIG51bWJlciBvZiBob3VycyBzdHVkZW50cyBzdHVkeSBwZXIgd2Vlaw0KDQojIyBBdmVyYWdlIE51bWJlciBvZiBIb3VycyBTdHVkZW50cyBTdHVkeSBwZXIgV2VlayAoV2l0aG91dCBDb25zaWRlcmluZyBPdGhlciBGYWN0b3JzKQ0KDQpOZXh0LCB3ZSBleHBsb3JlIHRoZSBhdmVyYWdlIG51bWJlciBvZiBob3VycyBzdHVkZW50cyBzdHVkeSBwZXIgd2VlayB3aXRob3V0IGNvbnNpZGVyaW5nIG90aGVyIGZhY3RvcnMuDQpgYGB7cn0NCiMgU3VtbWFyeSBzdGF0aXN0aWNzIGZvciBzdHVkeSBob3Vycw0Kc3VtbWFyeShzdHVkZW50X2RhdGEkSG91cnNfU3R1ZGllZCkNCmBgYA0KDQpUaGUgc3VtbWFyeSBzdGF0aXN0aWNzIHNob3cgdGhhdCB0aGUgYXZlcmFnZSBudW1iZXIgb2YgaG91cnMgc3R1ZGVudHMgc3R1ZHkgcGVyIHdlZWsgaXMgYXBwcm94aW1hdGVseSAxOS45OCBob3Vycy4gV2Ugd2lsbCBub3cgdmlzdWFsaXplIHRoZSBkaXN0cmlidXRpb24gb2Ygc3R1ZHkgaG91cnMgdXNpbmcgYSBoaXN0b2dyYW0uDQpgYGB7cn0NCiMgSGlzdG9ncmFtIG9mIHN0dWR5IGhvdXJzDQpoaXN0KHN0dWRlbnRfZGF0YSRIb3Vyc19TdHVkaWVkLCBtYWluID0gIkRpc3RyaWJ1dGlvbiBvZiBTdHVkeSBIb3VycyIsIHhsYWIgPSAiU3R1ZHkgSG91cnMiLCBjb2wgPSAic2t5Ymx1ZSIsIGJvcmRlciA9ICJibGFjayIpDQpgYGANCg0KIyMgQXZlcmFnZSBOdW1iZXIgb2YgSG91cnMgU3R1ZGVudHMgU3R1ZHkgcGVyIFdlZWsgKFBhcmVudGFsX0ludm9sdmVtZW50IENhdGVnb3J5KQ0KDQpOZXh0LCB3ZSB3aWxsIGV4cGxvcmUgdGhlIGF2ZXJhZ2UgbnVtYmVyIG9mIGhvdXJzIHN0dWRlbnRzIHN0dWR5IHBlciB3ZWVrIGJhc2VkIG9uIHBhcmVudGFsIGludm9sdmVtZW50IGxldmVscy4NCmBgYHtyfQ0KIyBTdW1tYXJ5IHN0YXRpc3RpY3MgZm9yIHN0dWR5IGhvdXJzIGJ5IHBhcmVudGFsIGludm9sdmVtZW50DQpzdW1tYXJ5KHN0dWRlbnRfZGF0YSRIb3Vyc19TdHVkaWVkW3N0dWRlbnRfZGF0YSRQYXJlbnRhbF9JbnZvbHZlbWVudCA9PSAiSGlnaCJdKQ0Kc3VtbWFyeShzdHVkZW50X2RhdGEkSG91cnNfU3R1ZGllZFtzdHVkZW50X2RhdGEkUGFyZW50YWxfSW52b2x2ZW1lbnQgPT0gIk1lZGl1bSJdKQ0Kc3VtbWFyeShzdHVkZW50X2RhdGEkSG91cnNfU3R1ZGllZFtzdHVkZW50X2RhdGEkUGFyZW50YWxfSW52b2x2ZW1lbnQgPT0gIkxvdyJdKQ0KYGBgDQoNClRoZSBzdW1tYXJ5IHN0YXRpc3RpY3Mgb2YgdGhlIGF2ZXJhZ2UgbnVtYmVyIG9mIGhvdXJzIHN0dWRlbnRzIHN0dWR5IHBlciB3ZWVrIGJhc2VkIG9uIHBhcmVudGFsIGludm9sdmVtZW50IGxldmVscyBkbyBub3Qgc2hvdyBzaWduaWZpY2FudCBkaWZmZXJlbmNlcy4gV2Ugd2lsbCBub3cgdXNlIEFOT1ZBIHRvIHRlc3QgZm9yIGRpZmZlcmVuY2VzIGluIHN0dWR5IGhvdXJzIGJhc2VkIG9uIHBhcmVudGFsIGludm9sdmVtZW50IGxldmVscy4gQnV0IGZpcnN0LCB3ZSBuZWVkIHRvIGNoZWNrIHRoZSBhc3N1bXB0aW9ucyBvZiBBTk9WQS4NCmBgYHtyfQ0KIyBTYW1wbGUgdGhlIGRhdGENCmhpZ2hfcGFyZW50YWxfaW52b2x2ZW1lbnQgPC0gc3R1ZGVudF9kYXRhJEhvdXJzX1N0dWRpZWRbc3R1ZGVudF9kYXRhJFBhcmVudGFsX0ludm9sdmVtZW50ID09ICJIaWdoIl1bc2FtcGxlKHN1bShzdHVkZW50X2RhdGEkUGFyZW50YWxfSW52b2x2ZW1lbnQgPT0gIkhpZ2giKSwgMTAwKV0NCm1lZGl1bV9wYXJlbnRhbF9pbnZvbHZlbWVudCA8LSBzdHVkZW50X2RhdGEkSG91cnNfU3R1ZGllZFtzdHVkZW50X2RhdGEkUGFyZW50YWxfSW52b2x2ZW1lbnQgPT0gIk1lZGl1bSJdW3NhbXBsZShzdW0oc3R1ZGVudF9kYXRhJFBhcmVudGFsX0ludm9sdmVtZW50ID09ICJNZWRpdW0iKSwgMTAwKV0NCmxvd19wYXJlbnRhbF9pbnZvbHZlbWVudCA8LSBzdHVkZW50X2RhdGEkSG91cnNfU3R1ZGllZFtzdHVkZW50X2RhdGEkUGFyZW50YWxfSW52b2x2ZW1lbnQgPT0gIkxvdyJdW3NhbXBsZShzdW0oc3R1ZGVudF9kYXRhJFBhcmVudGFsX0ludm9sdmVtZW50ID09ICJMb3ciKSwgMTAwKV0NCg0KIyBIaXN0b2dyYW0gb2Ygc3R1ZHkgaG91cnMgYnkgcGFyZW50YWwgaW52b2x2ZW1lbnQNCnBhcihtZnJvdyA9IGMoMSwgMykpDQpoaXN0KGhpZ2hfcGFyZW50YWxfaW52b2x2ZW1lbnQsIG1haW4gPSAiSGlnaCBQYXJlbnRhbCBJbnZvbHZlbWVudCIsIHhsYWIgPSAiU3R1ZHkgSG91cnMiLCBjb2wgPSAic2t5Ymx1ZSIsIGJvcmRlciA9ICJibGFjayIpDQpoaXN0KG1lZGl1bV9wYXJlbnRhbF9pbnZvbHZlbWVudCwgbWFpbiA9ICJNZWRpdW0gUGFyZW50YWwgSW52b2x2ZW1lbnQiLCB4bGFiID0gIlN0dWR5IEhvdXJzIiwgY29sID0gInNreWJsdWUiLCBib3JkZXIgPSAiYmxhY2siKQ0KaGlzdChsb3dfcGFyZW50YWxfaW52b2x2ZW1lbnQsIG1haW4gPSAiTG93IFBhcmVudGFsIEludm9sdmVtZW50IiwgeGxhYiA9ICJTdHVkeSBIb3VycyIsIGNvbCA9ICJza3libHVlIiwgYm9yZGVyID0gImJsYWNrIikNCg0KDQojIENoZWNrIGFzc3VtcHRpb25zIG9mIEFOT1ZBDQpzaGFwaXJvLnRlc3QoaGlnaF9wYXJlbnRhbF9pbnZvbHZlbWVudCkNCnNoYXBpcm8udGVzdChtZWRpdW1fcGFyZW50YWxfaW52b2x2ZW1lbnQpDQpzaGFwaXJvLnRlc3QobG93X3BhcmVudGFsX2ludm9sdmVtZW50KQ0KYGBgDQoNCkJvdGggdGhlIGhpc3RvZ3JhbXMgYW5kIHRoZSBTaGFwaXJvLVdpbGsgdGVzdCBzaG93IHRoYXQgdGhlIGRpc3RyaWJ1dGlvbiBvZiBzdHVkeSBob3VycyBpcyBhcHByb3hpbWF0ZWx5IG5vcm1hbCBmb3IgYWxsIHN0dWRlbnRzLiBXZSB3aWxsIG5vdyB1c2UgQU5PVkEgdG8gdGVzdCBmb3IgZGlmZmVyZW5jZXMgaW4gc3R1ZHkgaG91cnMgYmFzZWQgb24gcGFyZW50YWwgaW52b2x2ZW1lbnQgbGV2ZWxzLg0KYGBge3J9DQojIEFOT1ZBIHRlc3QgZm9yIHN0dWR5IGhvdXJzIGJ5IHBhcmVudGFsIGludm9sdmVtZW50DQphbm92YV9wYXJlbnRhbF9pbnZvbHZlbWVudCA8LSBhb3YoSG91cnNfU3R1ZGllZCB+IFBhcmVudGFsX0ludm9sdmVtZW50LCBkYXRhID0gc3R1ZGVudF9kYXRhKQ0Kc3VtbWFyeShhbm92YV9wYXJlbnRhbF9pbnZvbHZlbWVudCkNCmBgYA0KDQoNCg0KDQo=